package manage

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"os"
	"strings"

	"github.com/golang/protobuf/proto"
	"github.com/spf13/cobra"
	clicomm "hundsun.com/hsl/hschain/cmd/cli/common"
	"hundsun.com/hsl/hschain/common/types"
	"hundsun.com/hsl/hschain/common/util"
	"hundsun.com/hsl/hschain/contract/native/manage/common"
	"hundsun.com/hsl/hschain/protos"
	protoscommon "hundsun.com/hsl/hschain/protos/common"
	"hundsun.com/hsl/hschain/protos/config"
	"hundsun.com/hsl/hschain/protos/manage"
	service "hundsun.com/hsl/hschain/rpc/impl"
)

/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

const (
	manageName          = "manage"
	manageDes           = "manage the workflow"
	flagFlowName        = "flowName"
	flagFlowID          = "flowID"
	flagFlowCfg         = "flowCfg"
	flagFlowProposal    = "flowProposal"
	flagUserGroup       = "userGroup"
	flagProposalCfg     = "proposalCfg"
	flagConsensusType   = "consensusType"
	flagAddress         = "address"
	flagEffectiveHeight = "effective"
	flagStartHeight     = "start"
	flagEndHeight       = "end"
)

//Cmd ...
func Cmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   manageName,
		Short: manageDes,
		Long:  manageDes,
		Args:  cobra.MinimumNArgs(1),
	}

	cmd.AddCommand(setFlowCfgCmd())
	cmd.AddCommand(createCmd())
	cmd.AddCommand(voteCmd())
	cmd.AddCommand(queryCmd())
	cmd.AddCommand(closeFlowByFlowID())

	return cmd
}

func getProposalPayload(cmd *cobra.Command, proposalType manage.ProposalType) ([]byte, error) {
	CreateManageProposal, _ := cmd.Flags().GetString(flagFlowProposal)
	effectiveHeight, _ := cmd.Flags().GetUint64(flagEffectiveHeight)

	var proposal = &manage.ManageFlowProposal{Type: proposalType}
	switch proposalType {
	case manage.ProposalType_UserGroupProposalType:
		userGroup, _ := cmd.Flags().GetInt32(flagUserGroup)
		addresses := strings.Split(CreateManageProposal, ",")
		for _, addr := range addresses {
			err := protos.Address(addr).Validate()
			if err != nil {
				return nil, err
			}
		}
		proposal.FlowProposal = &manage.ManageFlowProposal_UserGroup{
			UserGroup: &manage.UserGroupProposal{
				Proposal:  addresses,
				GroupType: manage.UserGroupType(userGroup),
			},
		}
	case manage.ProposalType_SysParamProposalType:
		var sysParam = &config.SysParam{}
		cfgJSON, _ := cmd.Flags().GetString(flagProposalCfg)
		if strings.Contains(cfgJSON, "{") || strings.Contains(cfgJSON, "}") {
			json.Unmarshal([]byte(cfgJSON), sysParam)
		} else {
			filePtr, err := os.Open(cfgJSON)
			if err != nil {
				fmt.Printf("Open file failed [Err:%s]", err.Error())
				return nil, err
			}
			defer filePtr.Close()

			// 创建json解码器
			decoder := json.NewDecoder(filePtr)
			err = decoder.Decode(sysParam)
			if err != nil {
				fmt.Printf("decode config json file failed, err: %s\n", err.Error())
				return nil, err
			}
		}
		var sysParamProposal = &manage.SysParamProposal{}
		sysParamProposal.StepSysParam = &config.StepSysParam{SysParam: sysParam, EffectiveHeight: effectiveHeight}
		proposal.FlowProposal = &manage.ManageFlowProposal_SysParam{SysParam: sysParamProposal}
	case manage.ProposalType_ConsensusUpdateProposalType:
		var proposalInfo = &manage.ConsensusUpdateProposal{}
		var consensusParam = &config.ConsensusParam{}
		consensusType, _ := cmd.Flags().GetString(flagConsensusType)
		switch consensusType {
		case config.SoloConsensusType:
			if strings.Contains(CreateManageProposal, ",") {
				fmt.Printf("solo consensus only support one address:peerID pair\n")
				return nil, types.ErrInvalidParam
			}
			if !strings.Contains(CreateManageProposal, ":") {
				fmt.Printf("create proposal %s should be split with ':'\n", CreateManageProposal)
				return nil, types.ErrInvalidParam
			}
			addr := strings.Split(CreateManageProposal, ":")[0]
			peerID := strings.Split(CreateManageProposal, ":")[1]
			err := protos.Address(addr).Validate()
			if err != nil {
				return nil, err
			}

			if len(peerID) != common.PeerIDLength {
				fmt.Printf("invalid peerID %s\n", peerID)
				return nil, types.ErrInvalidParam
			}

			soloConsensusPayload := &config.ConsensusParam_SoloPayload{
				SoloPayload: &config.SoloConsensusConfigPayload{
					Address: addr,
					PeerID:  peerID,
				},
			}
			consensusParam.Type = config.SoloConsensusType
			consensusParam.ConsensusPayload = soloConsensusPayload
		case config.DposConsensusType:
			if !strings.Contains(CreateManageProposal, ",") {
				fmt.Printf("dpos consensus proposal %s should be split with ','\n", CreateManageProposal)
				return nil, types.ErrInvalidParam
			}
			var miners []*protoscommon.Miner
			for _, m := range strings.Split(CreateManageProposal, ",") {
				minerAddr := strings.Split(m, ":")[0]
				minerPeerID := strings.Split(m, ":")[1]
				err := protos.Address(minerAddr).Validate()
				if err != nil {
					return nil, err
				}
				miners = append(miners, &protoscommon.Miner{Address: minerAddr, PeerID: minerPeerID})
			}
			dposConsensusPayload := &config.ConsensusParam_DposPayload{
				DposPayload: &config.DposConsensusConfigPayload{DefaultMiners: miners},
			}
			consensusParam.Type = config.DposConsensusType
			consensusParam.ConsensusPayload = dposConsensusPayload
		}
		proposalInfo.StepConParam = &config.StepConParam{ConParam: consensusParam, EffectiveHeight: effectiveHeight}
		proposal.FlowProposal = &manage.ManageFlowProposal_ConsensusUpdate{ConsensusUpdate: proposalInfo}
	default:
		fmt.Printf("unknown proposal type: %d\n", proposalType)
		return nil, types.ErrInvalidParam
	}

	flowName, _ := cmd.Flags().GetString(flagFlowName)
	startHeight, _ := cmd.Flags().GetUint64(flagStartHeight)
	endHeight, _ := cmd.Flags().GetUint64(flagEndHeight)
	manageFlowPayload := manage.ManageFlowPayload{
		ManageFlowParam: &manage.ManageFlowPayload_CreateFlowParam{
			CreateFlowParam: &manage.ManageFlowCreateFlowParam{
				Name:        flowName,
				Proposal:    proposal,
				StartHeight: startHeight,
				EndHeight:   endHeight,
			},
		},
	}
	return proto.Marshal(&manageFlowPayload)
}

func createCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:              "create",
		Short:            "Create ManageFlow",
		Long:             "Create ManageFlow",
		TraverseChildren: false,
	}

	cmd.AddCommand(userGroupCmd())
	cmd.AddCommand(sysParamCmd())
	cmd.AddCommand(consensusCmd())
	return cmd
}

func userGroupCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "user",
		Short: "user group flow",
		Long:  "user group flow",
		RunE: func(cmd *cobra.Command, args []string) error {
			defer func() {
				err := recover()
				if err != nil {
					fmt.Println(err)
				}
			}()
			rpcAddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
			payload, err := getProposalPayload(cmd, manage.ProposalType_UserGroupProposalType)
			if err != nil {
				return err
			}

			tx, err := clicomm.BuildTxWithCmd(cmd, types.GenSysContractName(common.NativeManage), nil, payload)
			if err != nil {
				return err
			}

			clicomm.RPCCall(rpcAddr, service.ReceiveTransaction, tx, func(result interface{}) {
				fmt.Printf("transaction '%s' sent successfully\n", hex.EncodeToString(tx.Hash()))
			})
			return nil
		},
	}

	cmd.Flags().StringP(flagFlowName, "n", "", "flow name")
	cmd.Flags().StringP(flagFlowProposal, "p", "", "flow proposal")
	cmd.Flags().Int32P(flagUserGroup, "g", 0, "user group (0:mainBroad, 1:ConsensusOp, 2:CertsOp, 3:SysParamOp, 4:ParaChainOp, "+
		"5:GeneralOp, 6:ConsensusBoard, 7:CertsBoard, 8:SysParamBoard, 9:ParaChainBoard)")
	cmd.Flags().Uint64(flagStartHeight, 0, "start height")
	cmd.Flags().Uint64(flagEndHeight, 0, "end height")

	opts := []clicomm.CmdOption{
		clicomm.WithRequiredFlag(flagFlowName),
		clicomm.WithRequiredFlag(flagFlowProposal),
		clicomm.WithRequiredFlag(flagUserGroup),
		clicomm.WithRequiredFlag(flagStartHeight),
		clicomm.WithRequiredFlag(flagEndHeight),
		clicomm.WithHiddenFlag(clicomm.FlagTo),
		clicomm.WithHiddenFlag(clicomm.FlagAmount),
		clicomm.WithHiddenFlag(clicomm.FlagPayload),
		clicomm.WithHiddenFlag(clicomm.FlagExecTy),
	}

	clicomm.AddTransactionPublicFlag(cmd, opts...)

	return cmd
}

func sysParamCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "param",
		Short: "system param flow",
		Long:  "system param flow",
		RunE: func(cmd *cobra.Command, args []string) error {
			defer func() {
				err := recover()
				if err != nil {
					fmt.Println(err)
				}
			}()
			rpcAddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
			payload, err := getProposalPayload(cmd, manage.ProposalType_SysParamProposalType)
			if err != nil {
				return err
			}

			tx, err := clicomm.BuildTxWithCmd(cmd, types.GenSysContractName(common.NativeManage), nil, payload)
			if err != nil {
				return err
			}
			clicomm.RPCCall(rpcAddr, service.ReceiveTransaction, tx, func(result interface{}) {
				fmt.Printf("transaction '%s' sent successfully\n", hex.EncodeToString(tx.Hash()))
			})
			return nil
		},
	}

	cmd.Flags().StringP(flagFlowName, "n", "", "flow name")
	cmd.Flags().StringP(flagProposalCfg, "c", "", "proposal cfg")
	cmd.Flags().Uint64(flagStartHeight, 0, "start height")
	cmd.Flags().Uint64(flagEndHeight, 0, "end height")
	cmd.Flags().Uint64(flagEffectiveHeight, 0, "effective height")

	opts := []clicomm.CmdOption{
		clicomm.WithRequiredFlag(flagFlowName),
		clicomm.WithRequiredFlag(flagProposalCfg),
		clicomm.WithRequiredFlag(flagStartHeight),
		clicomm.WithRequiredFlag(flagEndHeight),
		clicomm.WithHiddenFlag(clicomm.FlagAmount),
		clicomm.WithHiddenFlag(clicomm.FlagTo),
		clicomm.WithHiddenFlag(clicomm.FlagPayload),
		clicomm.WithHiddenFlag(clicomm.FlagExecTy),
	}
	clicomm.AddTransactionPublicFlag(cmd, opts...)

	return cmd
}

func consensusCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "consensus",
		Short: "consensus update flow",
		Long:  "consensus update flow",
		RunE: func(cmd *cobra.Command, args []string) error {
			defer func() {
				err := recover()
				if err != nil {
					fmt.Println(err)
				}
			}()
			rpcAddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
			payload, err := getProposalPayload(cmd, manage.ProposalType_ConsensusUpdateProposalType)
			if err != nil {
				return err
			}

			tx, err := clicomm.BuildTxWithCmd(cmd, types.GenSysContractName(common.NativeManage), nil, payload)
			if err != nil {
				return err
			}
			clicomm.RPCCall(rpcAddr, service.ReceiveTransaction, tx, func(result interface{}) {
				fmt.Printf("transaction '%s' sent successfully\n", hex.EncodeToString(tx.Hash()))
			})
			return nil
		},
	}

	cmd.Flags().StringP(flagFlowName, "n", "", "flow name")
	cmd.Flags().StringP(flagFlowProposal, "p", "", "flow proposal")
	cmd.Flags().StringP(flagConsensusType, "c", "", "consensus type")
	cmd.Flags().Uint64(flagStartHeight, 0, "start height")
	cmd.Flags().Uint64(flagEndHeight, 0, "end height")
	cmd.Flags().Uint64(flagEffectiveHeight, 0, "effective height")

	opts := []clicomm.CmdOption{
		clicomm.WithRequiredFlag(flagFlowName),
		clicomm.WithRequiredFlag(flagFlowProposal),
		clicomm.WithRequiredFlag(flagConsensusType),
		clicomm.WithRequiredFlag(flagStartHeight),
		clicomm.WithRequiredFlag(flagEndHeight),
		clicomm.WithHiddenFlag(clicomm.FlagAmount),
		clicomm.WithHiddenFlag(clicomm.FlagTo),
		clicomm.WithHiddenFlag(clicomm.FlagPayload),
		clicomm.WithHiddenFlag(clicomm.FlagExecTy),
	}
	clicomm.AddTransactionPublicFlag(cmd, opts...)

	return cmd
}

func closeFlowByFlowID() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "closeFlow",
		Short: "close flow",
		Long:  "close flow",
		RunE: func(cmd *cobra.Command, args []string) error {
			defer func() {
				err := recover()
				if err != nil {
					fmt.Println(err)
				}
			}()
			rpcAddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
			flowID, _ := cmd.Flags().GetUint32(flagFlowID)
			manageFlowPayload := manage.ManageFlowPayload{
				ManageFlowParam: &manage.ManageFlowPayload_CloseFlowParam{
					CloseFlowParam: &manage.ManageCloseFlowParam{
						FlowID: flowID,
					},
				},
			}

			payload, _ := proto.Marshal(&manageFlowPayload)
			tx, err := clicomm.BuildTxWithCmd(cmd, types.GenSysContractName(common.NativeManage), nil, payload)
			if err != nil {
				return err
			}

			clicomm.RPCCall(rpcAddr, service.ReceiveTransaction, tx, func(result interface{}) {
				fmt.Printf("transaction '%s' sent successfully\n", hex.EncodeToString(tx.Hash()))
			})
			return nil
		},
	}
	cmd.Flags().Uint32(flagFlowID, 0, "flowID")

	opts := []clicomm.CmdOption{
		clicomm.WithRequiredFlag(flagFlowID),
		clicomm.WithHiddenFlag(clicomm.FlagAmount),
		clicomm.WithHiddenFlag(clicomm.FlagTo),
		clicomm.WithHiddenFlag(clicomm.FlagPayload),
		clicomm.WithHiddenFlag(clicomm.FlagExecTy),
	}
	clicomm.AddTransactionPublicFlag(cmd, opts...)

	return cmd
}

func voteCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "vote",
		Short: "Vote Manage",
		Long:  "Vote Manage",
		RunE: func(cmd *cobra.Command, args []string) error {
			defer func() {
				err := recover()
				if err != nil {
					fmt.Println(err)
				}
			}()
			rpcAddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
			flowID, _ := cmd.Flags().GetUint32(flagFlowID)
			manageFlowPayload := manage.ManageFlowPayload{
				ManageFlowParam: &manage.ManageFlowPayload_VoteParam{
					VoteParam: &manage.ManageFlowVoteParam{
						FlowID: flowID,
					},
				},
			}
			payload, _ := proto.Marshal(&manageFlowPayload)
			tx, err := clicomm.BuildTxWithCmd(cmd, types.GenSysContractName(common.NativeManage), nil, payload)
			if err != nil {
				return err
			}

			clicomm.RPCCall(rpcAddr, service.ReceiveTransaction, tx, func(result interface{}) {
				fmt.Printf("transaction '%s' sent successfully\n", hex.EncodeToString(tx.Hash()))
			})
			return nil
		},
	}

	cmd.Flags().Uint32(flagFlowID, 0, "flowID to vote")

	opts := []clicomm.CmdOption{
		clicomm.WithRequiredFlag(flagFlowID),
		clicomm.WithHiddenFlag(clicomm.FlagAmount),
		clicomm.WithHiddenFlag(clicomm.FlagTo),
		clicomm.WithHiddenFlag(clicomm.FlagPayload),
		clicomm.WithHiddenFlag(clicomm.FlagExecTy),
	}
	clicomm.AddTransactionPublicFlag(cmd, opts...)

	return cmd
}
func setFlowCfgCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "setFlowCfg",
		Short: "Set FlowCfg",
		Long:  "Set FlowCfg",
		RunE: func(cmd *cobra.Command, args []string) error {
			defer func() {
				err := recover()
				if err != nil {
					fmt.Println(err)
				}
			}()
			rpcAddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
			cfg, _ := cmd.Flags().GetString(flagFlowCfg)

			var manageFlowCreateCfgParam manage.ManageFlowCreateCfgParam
			if strings.Contains(cfg, "{") || strings.Contains(cfg, "}") {
				json.Unmarshal([]byte(cfg), &manageFlowCreateCfgParam)
			} else {
				filePtr, err := os.Open(cfg)
				if err != nil {
					fmt.Printf("Open file failed [Err:%s]", err.Error())
					return err
				}
				defer filePtr.Close()

				// 创建json解码器
				decoder := json.NewDecoder(filePtr)
				err = decoder.Decode(&manageFlowCreateCfgParam)
			}
			manageFlowPayload := manage.ManageFlowPayload{
				ManageFlowParam: &manage.ManageFlowPayload_CreateCfgParam{
					CreateCfgParam: &manageFlowCreateCfgParam,
				},
			}
			payload, err := proto.Marshal(&manageFlowPayload)
			if err != nil {
				return err
			}

			tx, err := clicomm.BuildTxWithCmd(cmd, types.GenSysContractName(common.NativeManage), nil, payload)
			if err != nil {
				return err
			}

			clicomm.RPCCall(rpcAddr, service.ReceiveTransaction, tx, func(result interface{}) {
				fmt.Printf("transaction '%s' sent successfully\n", hex.EncodeToString(tx.Hash()))
			})
			return nil
		},
	}

	cmd.Flags().String(flagFlowCfg, "", "cfg of manageFlow")

	opts := []clicomm.CmdOption{
		clicomm.WithRequiredFlag(flagFlowCfg),
		clicomm.WithHiddenFlag(clicomm.FlagAmount),
		clicomm.WithHiddenFlag(clicomm.FlagTo),
		clicomm.WithHiddenFlag(clicomm.FlagPayload),
		clicomm.WithHiddenFlag(clicomm.FlagExecTy),
	}

	clicomm.AddTransactionPublicFlag(cmd, opts...)

	return cmd
}

func queryCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "query",
		Short: "query",
	}

	cmd.AddCommand(
		queryFlowStatusCmd(),
		queryUserGroupCmd(),
		queryFlowCfgByName(),
		queryCreateFlow(),
	)

	return cmd
}

func queryFlowStatusCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "flowStatus",
		Short: "query flow status",
		Run:   queryFlowStatus,
	}

	cmd.Flags().Uint32P(flagFlowID, "i", 0, "flow id")
	cmd.MarkFlagRequired(flagFlowID)

	return cmd
}

func queryFlowStatus(cmd *cobra.Command, args []string) {
	flowID, _ := cmd.Flags().GetUint32(flagFlowID)
	flowParam := &manage.ManageFlowQueryFlowParam{
		FlowID: flowID,
	}
	req, err := clicomm.CreateQueryContractReq(common.NativeManage, common.QueryManageFlowStatus, flowParam)
	if err != nil {
		fmt.Printf("create query contract request failed, err: %s", err.Error())
		return
	}

	rpcLaddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
	clicomm.RPCCall(rpcLaddr, service.QueryContract, req,
		func(res interface{}) {
			obj := res.(service.JSONRPCResp)
			val, _ := util.Bytes2Struct(&manage.ManageFlowStatus{}, obj.Payload)
			clicomm.PrintJSON(val)
		},
	)
}

func queryUserGroupCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "userGroup",
		Short: "query user group info",
		Run:   queryUserGroup,
	}

	cmd.Flags().Int32P(flagUserGroup, "g", 0, "user group (0:mainBroad, 1:ConsensusOp, 2:CertsOp, 3:SysParamOp, 4:ParaChainOp, "+
		"5:GeneralOp, 6:ConsensusBoard, 7:CertsBoard, 8:SysParamBoard, 9:ParaChainBoard)")
	cmd.MarkFlagRequired(flagUserGroup)

	return cmd
}

func queryUserGroup(cmd *cobra.Command, args []string) {
	groupType, _ := cmd.Flags().GetInt32(flagUserGroup)
	manageGroupType := manage.UserGroupType(groupType)
	if manageGroupType < manage.UserGroupType_MainBoard ||
		manageGroupType > manage.UserGroupType_ParaChainBoard {
		fmt.Println("invalid user group type")
		return
	}

	var param = &manage.ManageFlowQueryUserGroup{GroupType: manageGroupType}
	req, err := clicomm.CreateQueryContractReq(common.NativeManage, common.QueryUserGroup, param)
	if err != nil {
		fmt.Printf("create query contract request failed, err: %s", err.Error())
		return
	}

	rpcLaddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
	clicomm.RPCCall(rpcLaddr, service.QueryContract, req,
		func(res interface{}) {
			obj := res.(service.JSONRPCResp)
			val, _ := util.Bytes2Struct(&manage.ManageFlowGroupInfo{}, obj.Payload)
			clicomm.PrintJSON(val)
		},
	)
}

//func queryFlowCfgByName
func queryFlowCfgByName() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "flowCfg",
		Short: "query flowCfg by name",
		Run:   queryFlowCfg,
	}

	cmd.Flags().String(flagFlowName, "nil", "flow config name")
	cmd.MarkFlagRequired(flagFlowName)
	return cmd
}
func queryFlowCfg(cmd *cobra.Command, args []string) {
	cfgName, _ := cmd.Flags().GetString(flagFlowName)
	cfgParam := &manage.ManageFlowQueryCfgParam{
		Name: cfgName,
	}

	req, err := clicomm.CreateQueryContractReq(common.NativeManage, common.QueryManageFlowCfg, cfgParam)
	if err != nil {
		fmt.Printf("create query contract request failed, err: %s", err.Error())
		return
	}

	rpcLaddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
	clicomm.RPCCall(rpcLaddr, service.QueryContract, req,
		func(res interface{}) {
			obj := res.(service.JSONRPCResp)
			val, _ := util.Bytes2Struct(&manage.ManageFlowCfg{}, obj.Payload)
			clicomm.PrintJSON(val)
		},
	)
}

func queryCreateFlow() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "flow",
		Short: "query flow by address",
		Run:   queryFlowByAddress,
	}
	cmd.Flags().Uint32P(flagFlowID, "i", 0, "flow id")
	cmd.Flags().StringP(flagAddress, "a", "", "address")
	cmd.MarkFlagRequired(flagAddress)

	return cmd
}
func queryFlowByAddress(cmd *cobra.Command, args []string) {
	address, _ := cmd.Flags().GetString(flagAddress)
	id, _ := cmd.Flags().GetUint32(flagFlowID)

	if err := protos.Address(address).Validate(); err != nil {
		fmt.Printf("address %s validate failed, err: %s\n", address, err.Error())
		return
	}

	createFlow := &manage.ManageFlowQueryCreateFlow{
		Address: address,
		Id:      id,
	}

	req, err := clicomm.CreateQueryContractReq(common.NativeManage, common.QueryCreatedManageFlowByAddr, createFlow)
	if err != nil {
		fmt.Printf("create query contract request failed, err: %s\n", err.Error())
		return
	}

	rpcLaddr, _ := cmd.Flags().GetString(clicomm.FlagRPCLaddr)
	clicomm.RPCCall(rpcLaddr, service.QueryContract, req,
		func(res interface{}) {
			obj := res.(service.JSONRPCResp)
			val, _ := util.Bytes2Struct(&manage.ManageFlowCreateFlowResp{}, obj.Payload)
			clicomm.PrintJSON(val)
		},
	)
}
